package modularity.passiveDrift;

import java.util.Properties;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import ec.util.MersenneTwisterFast;

public class ModuleMutatorManager implements MutationManager{

	protected double mergeModuleProb;
	protected double splitModuleProb;
	protected double duplicateModuleProb;
	protected double removeModuleProb;

	protected BasicMutatorManager basicManager;
	private int mutationThreads;

	public ModuleMutatorManager(Properties arguments){
		basicManager = new BasicMutatorManager(arguments);
		mergeModuleProb = Double.valueOf(arguments.getProperty("merge-module", "0.1"));
		splitModuleProb = Double.valueOf(arguments.getProperty("split-module", "0.1"));
		duplicateModuleProb = Double.valueOf(arguments.getProperty("duplicate-module", "0.1"));
		removeModuleProb = Double.valueOf(arguments.getProperty("remove-module", "0.1"));
	}

	public void mutate(ListedPopulation pop) {
		int populationsize = pop.size();
		ExecutorService eservice = Executors.newFixedThreadPool(mutationThreads);
		CompletionService<Object> cservice = new ExecutorCompletionService<Object>(eservice);

		for(int i = 0; i < populationsize; i++){
			BasicMutator mut = new BasicMutator(basicManager.getRemoveConnectionProb(), basicManager.getAddConnectionProb(), basicManager.getAddNodeProb());
			cservice.submit(new MutationTask(pop.get(i), i, new ModuleMutator(mut, mergeModuleProb, splitModuleProb, duplicateModuleProb, removeModuleProb), new MersenneTwisterFast()));
		}

		eservice.shutdown();
		
		for(int index = 0; index < populationsize; index++) {
			Object result;
			try {
				result = cservice.take().get();
			} catch (InterruptedException e) {
	            // Something went wrong with a task submitted
	            System.out.println("Error Interrupted exception");
	            e.printStackTrace();
	        } catch (ExecutionException e) {
	            // Something went wrong with the result
	            e.printStackTrace();
	            System.out.println("Error get() threw exception");
	        }
		}
		
	}

	public void setMutationThreads(int threads){
		this.mutationThreads = threads;
	}



}
